#!/usr/bin/env python
"""
Addama Authorization Services

Provides an API for authorization services via addama-login.

For more information, please see the documentation in README.txt, or simply
issue help() on any function or module contained within this package.

For license information, please see LICENSE.txt.


Author: Tom Robinson <trobinson@systemsbiology.org>
Initial Revision: April 14th, 2010

"""

# Imports

import cookielib
import Cookie
import urllib
import urllib2
from getpass import getpass


# Functions

def login(url, username, password):
    """Logs into Addama via addama-login
    Returns the credentials as a cookielib.CookieJar object"""
    
    # Preconditions
    if len(url) == 0:
        raise ValueError
    # Invariants: username and password can be blank

    authCookies = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(authCookies))
    
    request = opener.open(url,urllib.urlencode({'username':username,'password':password}))

    return authCookies

def interactiveLogin(url=None, username=None, password=None):
    """Interactively logs into Addama via addama-login
    Returns the credentials as a cookielib.CookieJar object

    Prompts user for any information not provided at invocation. 
    If URL, username, and password are provided outright, this function will
    pass that information directly to login(...), instead of prompting."""
    if not url:
        url = raw_input('Login URL: ')
    if not username:
        username = raw_input('Username: ')
    if not password:
        password = getpass('Password: ')
    authCookies = login(url, username, password)

    # Clear plaintext username and password information
    del username,password
    return authCookies

def saveCookies(fileLocation, authCookies=None):
    """Saves cookies to file in LWP string format
    If no authCookies are supplied, this creates a blank file."""

    # Save cookies to file
    cookieFile = cookielib.LWPCookieJar(fileLocation)

    # @hack This is a clear violation of The Law of Demeter. Unfortunately,
    # this is the expected iteration interface for cookielib.CookieJar.
    
    # Write LWP cookies only if a cookieJar was given
    if authCookies:
        iterCookies = authCookies.__iter__()
        while True:
            try:
                cookieFile.set_cookie(iterCookies.next())
            except StopIteration:
                break
            # Invariant: iterCookies MUST raise StopIteration
        
    cookieFile.save()
    # Postcondition: fileLocation now contains an LWP formatted cookie file

def loadCookies(fileLocation, authCookies=None):
    """Loads cookies from an LWP string cookie file
    Returns loaded cookies as a cookielib.CookieJar object"""

    # Load cookies from file
    cookieFile = cookielib.LWPCookieJar(fileLocation)
    cookieFile.load()

    # If authCookies is not supplied, build it
    if not authCookies:
        authCookies = cookielib.CookieJar()

    # Read LWP cookies from disk
    iterCookies = cookieFile.__iter__()
    while True:
        try:
            authCookies.set_cookie(iterCookies.next())
        except StopIteration:
            break
        # Invariant: iterCookies MUST raise StopIteration
                
    return authCookies


# Output help text if this script is invoked directly
if __name__ == "__main__":
    print """
This script should not be run directly.

To include it in your project, simply import it from addama:
import <directory>
from <module> import <submodule>

For example:
import addama.api
from addama import api

(Note these two invocations differ as to the syntax of the final module)

"""

